package com.test.Aspect;

import com.test.enums.Replay;
import com.test.enums.ReplayCode;
import com.test.utils.ReplayUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;

@ResponseBody
@ControllerAdvice
public class MyControllerAdvice {

    private static final String logExceptionFormat = "Capture Exception By GlobalExceptionHandler: Code: %s Detail: %s";
    private final static Logger LOGGER = LoggerFactory.getLogger(MyControllerAdvice.class);


//    @ExceptionHandler(value = Exception.class)
//    public Map<String,Object> errorHandle(Exception e){
//        Map<String,Object> map = new HashMap<String,Object>();
//        map.put("code",-1);
//        map.put("msg",e.getMessage());
//        return map;
//    }

    /**
    * 判断错误是否是已定义的已知错误，不是则由未知错误代替，同时记录在log中
    * @param e
    * @return
    */
    @ExceptionHandler(BusinessException.class)
    public Replay BusinessException(BusinessException e){

        LOGGER.error("【系统异常】{}",e);
        return ReplayUtil.error(e.getCode(),e.getMsg());
    }

    //运行时异常
    @ExceptionHandler(RuntimeException.class)
    public Replay runtimeExceptionHandler(RuntimeException ex) {
        return resultFormat(2, ex);
    }

    //空指针异常
    @ExceptionHandler(NullPointerException.class)
    public Replay nullPointerExceptionHandler(NullPointerException ex) {
        return resultFormat(3, ex);
    }

    //类型转换异常
    @ExceptionHandler(ClassCastException.class)
    public Replay classCastExceptionHandler(ClassCastException ex) {
        return resultFormat(4, ex);
    }

    //IO异常
    @ExceptionHandler(IOException.class)
    public Replay iOExceptionHandler(IOException ex) {
        return resultFormat(5, ex);
    }

    //未知方法异常
    @ExceptionHandler(NoSuchMethodException.class)
    public Replay noSuchMethodExceptionHandler(NoSuchMethodException ex) {
        return resultFormat(6, ex);
    }

    //数组越界异常
    @ExceptionHandler(IndexOutOfBoundsException.class)
    public Replay indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex) {
        return resultFormat(7, ex);
    }

    //400错误
    @ExceptionHandler({HttpMessageNotReadableException.class})
    public Replay requestNotReadable(HttpMessageNotReadableException ex) {
        System.out.println("400..requestNotReadable");
        return resultFormat(8, ex);
    }

    //400错误
    @ExceptionHandler({TypeMismatchException.class})
    public Replay requestTypeMismatch(TypeMismatchException ex) {
        System.out.println("400..TypeMismatchException");
        return resultFormat(9, ex);
    }

    //400错误
    @ExceptionHandler({MissingServletRequestParameterException.class})
    public Replay requestMissingServletRequest(MissingServletRequestParameterException ex) {
        System.out.println("400..MissingServletRequest");
        return resultFormat(10, ex);
    }

    //405错误
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public Replay request405(HttpRequestMethodNotSupportedException ex) {
        return resultFormat(11, ex);
    }

    //406错误
    @ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
    public Replay request406(HttpMediaTypeNotAcceptableException ex) {
        System.out.println("406...");
        return resultFormat(12, ex);
    }

    //500错误
    @ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
    public Replay server500(RuntimeException ex) {
        System.out.println("500...");
        return resultFormat(13, ex);
    }

    //栈溢出
    @ExceptionHandler({StackOverflowError.class})
    public Replay requestStackOverflow(StackOverflowError ex) {
        return resultFormat(14, ex);
    }

    //其他错误
    @ExceptionHandler({Exception.class})
    public Replay exception(Exception ex) {
        return resultFormat(15, ex);
    }

    private <T extends Throwable> Replay resultFormat(Integer code, T ex) {
        ex.printStackTrace();
        LOGGER.error(String.format(logExceptionFormat, code, ex.getMessage()));
        return ReplayUtil.error(code, ex.getMessage());
    }

}